From 6eeeaeb211e6d1f9f676c7f5e4aaa0e000537977 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 25 Nov 2009 14:19:20 +0000 Subject: [PATCH] libxenlight: clean up the domain when it dies This patch adds two functions to libxenlight to be able to recognize when a particular domain dies. After creating a domain, xl uses these functions to wait for its death and clean up its resources. Signed-off-by: Stefano Stabellini --- tools/libxl/libxl.c | 63 ++++++++++++++++++++++++++++++++++++++++----- tools/libxl/libxl.h | 4 +++ tools/libxl/xl.c | 39 +++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 8 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 47fe8e1ea6..da2d1dfce1 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -54,9 +54,18 @@ int libxl_ctx_free(struct libxl_ctx *ctx) { libxl_free_all(ctx); free(ctx->alloc_ptrs); - ctx->alloc_ptrs = NULL; + ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *)); + if (!ctx->alloc_ptrs) + return ERROR_NOMEM; + return 0; +} + +int libxl_ctx_close(struct libxl_ctx *ctx) +{ + libxl_ctx_free(ctx); + free(ctx->alloc_ptrs); xc_interface_close(ctx->xch); - xs_daemon_close(ctx->xsh); + xs_daemon_close(ctx->xsh); return 0; } @@ -352,6 +361,46 @@ int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req) return 0; } +int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd) +{ + if (!xs_watch(ctx->xsh, "@releaseDomain", "domain_death")) + return -1; + *fd = xs_fileno(ctx->xsh); + return 0; +} + +int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info) +{ + unsigned int num; + int nb_domain, i, rc = 0; + char **vec = NULL; + xc_dominfo_t *list = NULL; + + vec = xs_read_watch(ctx->xsh, &num); + if (!vec) + return 0; + if (!strcmp(vec[XS_WATCH_TOKEN], "domain_death")) { + list = libxl_domain_infolist(ctx, &nb_domain); + for (i = 0; i < nb_domain; i++) { + if (domid == list[i].domid) { + if (list[i].running || (!list[i].shutdown && !list[i].crashed && !list[i].dying)) + goto out; + *info = list[i]; + rc = 1; + goto out; + } + } + memset(info, 0x00, sizeof(xc_dominfo_t)); + rc = 1; + goto out; + } + +out: + free(list); + free(vec); + return rc; +} + static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid) { char *pid; @@ -409,11 +458,6 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force) } if (libxl_destroy_device_model(ctx, domid) < 0) XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid); - rc = xc_domain_destroy(ctx->xch, domid); - if (rc < 0) { - XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid); - return -1; - } if (libxl_devices_destroy(ctx, domid, force) < 0) XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid); if (!xs_rm(ctx->xsh, XBT_NULL, dom_path)) @@ -421,6 +465,11 @@ int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force) snprintf(vm_path, sizeof(vm_path), "/vm/%s", libxl_uuid_to_string(ctx, uuid)); if (!xs_rm(ctx->xsh, XBT_NULL, vm_path)) XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path); + rc = xc_domain_destroy(ctx->xch, domid); + if (rc < 0) { + XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid); + return -1; + } return 0; } diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 890f5c8c49..b568bc4863 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -227,6 +227,7 @@ typedef struct { /* context functions */ int libxl_ctx_init(struct libxl_ctx *ctx); int libxl_ctx_free(struct libxl_ctx *ctx); +int libxl_ctx_close(struct libxl_ctx *ctx); int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, void *log_data); /* domain related functions */ @@ -239,6 +240,9 @@ int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info, int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req); int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force); +int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, int *fd); +int libxl_is_domain_dead(struct libxl_ctx *ctx, uint32_t domid, xc_dominfo_t *info); + int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid); int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid); diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c index c984f156f4..4c74660951 100644 --- a/tools/libxl/xl.c +++ b/tools/libxl/xl.c @@ -25,7 +25,10 @@ #include /* for time */ #include #include +#include +#include #include +#include #include #include @@ -584,7 +587,8 @@ static void create_domain(int debug, const char *filename) libxl_device_vkb *vkbs = NULL; libxl_device_console console; int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0; - int i; + int i, fd; + int need_daemon = 1; libxl_device_model_starting *dm_starting = 0; printf("Parsing config file %s\n", filename); @@ -592,6 +596,9 @@ static void create_domain(int debug, const char *filename) if (debug) printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info); +start: + domid = 0; + libxl_ctx_init(&ctx); libxl_ctx_set_log(&ctx, log_callback, NULL); libxl_domain_make(&ctx, &info1, &domid); @@ -632,6 +639,36 @@ static void create_domain(int debug, const char *filename) libxl_domain_unpause(&ctx, domid); + if (need_daemon) { + daemon(0, 0); + need_daemon = 0; + } + + libxl_wait_for_domain_death(&ctx, domid, &fd); + while (1) { + int ret; + fd_set rfds; + xc_dominfo_t info; + memset(&info, 0x00, sizeof(xc_dominfo_t)); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + ret = select(fd + 1, &rfds, NULL, NULL, NULL); + if (!ret) + continue; + if (libxl_is_domain_dead(&ctx, domid, &info)) { + if (info.crashed || info.dying || (info.shutdown && (info.shutdown_reason != SHUTDOWN_suspend))) { + libxl_domain_destroy(&ctx, domid, 0); + if (info.shutdown && (info.shutdown_reason == SHUTDOWN_reboot)) { + libxl_ctx_free(&ctx); + goto start; + } + } + exit(0); + } + } + for (i = 0; i < num_vifs; i++) { free(vifs[i].smac); free(vifs[i].ifname); -- 2.30.2